# -*- coding: utf-8 -*-
__author__ = 'lztkdr'
__date__ = '2020/4/9 20:48'

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

# Pycharm输出窗口有省略号，数据显示不全解决方法
pd.set_option('display.max_rows', 10)
pd.set_option('display.max_columns', 200)
pd.set_option('display.width', 1000)

# 如果要显示中文标题和坐标表示，需要添加以下两行代码
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False

"""

在日常的数据处理中，经常会对一个DataFrame进行逐行、逐列和逐元素的操作，对应这些操作，
Pandas中的map、apply和applymap可以解决绝大部分这样的数据处理需求

https://mp.weixin.qq.com/s?__biz=MjM5MjAwODM4MA==&mid=2650737590&idx=3&sn=62cd4cc09551e9a4583651f6d71b9538&chksm=bea77a6589d0f3737d98ece41cada79c416c6afc20cf5e85f97260119b89fe1e1c62b7998842&mpshare=1&scene=23&srcid=0409iB7DbRhfx8pRrkRxokYB&sharer_sharetime=1586425673328&sharer_shareid=d267f26442147f9849f60be756ca88c5#rd

"""
print('============================================================================================================')

boolean = [True, False]
gender = ["男", "女"]
color = ["white", "black", "yellow"]
data = pd.DataFrame(
	{
		"height": np.random.randint(150, 190, 100),
		"weight": np.random.randint(40, 90, 100),
		"smoker": [boolean[x] for x in np.random.randint(0, 2, 100)],
		"gender": [gender[x] for x in np.random.randint(0, 2, 100)],
		"age": np.random.randint(15, 90, 100),
		"color": [color[x] for x in np.random.randint(0, len(color), 100)]
	})
print(data)
print('==========================================')
"""
如果需要把数据集中gender列的男替换为1，女替换为0，怎么做呢？绝对不是用for循环实现！！！
使用Series.map()可以很容易做到，最少仅需一行代码。
"""

# ①使用字典进行映射
data["gender"] = data["gender"].map({"男": 1, "女": 0})


# ②使用函数
def gender_map(x):
	gender = 1 if x == "男" else 0
	return gender


# 注意这里传入的是函数名，不带括号
data["gender"] = data["gender"].map(gender_map)

print('==========================================')
"""
apply

同时Series对象还有apply方法，apply方法的作用原理和map方法类似，区别在于apply能够传入功能更为复杂的函数。
怎么理解呢？一起看看下面的例子。
	假设在数据统计的过程中，年龄age列有较大误差，需要对其进行调整（加上或减去一个值），
	由于这个加上或减去的值未知，故在定义函数时，需要加多一个参数bias，
	此时用map方法是操作不了的（传入map的函数只能接收一个参数），apply方法则可以解决这个问题
"""
# lambda 表达式 appaly 方式1：
data.age = data.age.apply(lambda x: x + 3)

# appaly 传入方法名 方式2：
def apply_age(x, bias):
	return x + bias

# 以元组的方式传入额外的参数
data["age"] = data["age"].apply(apply_age, args=(-3,))

print(data.age)
print('=======================')

# 沿着0轴求和
srs = data[["height","weight","age"]].apply(np.sum, axis=0)
print(srs)

# height    17066
# weight     6712
# age        4951
# dtype: int64

print('==========================================')
#
# applymap
#
# applymap的用法比较简单，会对DataFrame中的每个单元格执行指定函数的操作，虽然用途不如apply广泛，但在某些场合下还是比较有用的，如下面这个例子。

df = pd.DataFrame(
    {
        "A":np.random.randn(5),
        "B":np.random.randn(5),
        "C":np.random.randn(5),
        "D":np.random.randn(5),
        "E":np.random.randn(5),
    }
)
print(df)
# 现在想将DataFrame中所有的值保留两位小数显示，使用applymap可以很快达到你想要的目的，

print(df.applymap(lambda x:"%.2f" % x))

print(df)




